# -*- coding: utf-8 -*-

import sys
from urllib import urlencode
from urlparse import parse_qsl, urlparse
import xbmcgui
import xbmcplugin
import requests
#import re
from bs4 import BeautifulSoup
#import base64
#import resolveurl as urlresolver

# Get the plugin url in plugin:// notation.
_url = sys.argv[0]
# Get the plugin handle as an integer number.
_handle = int(sys.argv[1])

#Genre and search are special functions
VIDEOS = {
	"Newest" : "http://hentaihaven.org/?sort=date",
	"Most Fapped" : "http://hentaihaven.org/?sort=faps",
	"Most Viewed" : "http://hentaihaven.org/?sort=views",
	"Popular" : "http://hentaihaven.org/?sort=popular",
	"By Name" : "http://hentaihaven.org/?sort=title",
	"By Year" : "http://hentaihaven.org/?sort=year",
	"Genres" : "http://hentaihaven.org/pick-your-poison/",
	"Search" : None
	}


def get_url(**kwargs):
	"""
	Create a URL for calling the plugin recursively from the given set of keyword arguments.

	:param kwargs: "argument=value" pairs
	:type kwargs: dict
	:return: plugin call URL
	:rtype: str
	"""
	return '{0}?{1}'.format(_url, urlencode(kwargs))

def get_videos(category):
	"""
	Get the list of videofiles/streams.

	Here you can insert some parsing code that retrieves
	the list of video streams in the given category from some site or server.

	.. note:: Consider using `generators functions <https://wiki.python.org/moin/Generators>`_
		instead of returning lists.

	:param category: Category name
	:type category: str
	:return: the list of videos in the category
	:rtype: list
	"""
	
	return VIDEOS[category]

def search():
	kb = xbmc.Keyboard('default', 'heading')
	kb.setDefault('')
	kb.setHeading('Search For Anime')
	kb.setHiddenInput(False)
	kb.doModal()
	if kb.isConfirmed():
		r = requests.post("http://www.animemobile.com/search", data={"anime":kb.getText()})
		return list_anime_series_full("Search Results", r)
	return False;

def list_genres():
	"""
	Display available genres.
	"""
	xbmcplugin.setPluginCategory(_handle, 'Browse by Genre')
	xbmcplugin.setContent(_handle, 'videos')
	# Get genres
	site = requests.get(VIDEOS["Genres"])
	soup = BeautifulSoup(site.text, "html.parser")
	genres = soup.find(class_="taglist").find_all("span")
	
	# Iterate through categories
	for genre in genres:
		genreName = genre.a.get_text()
		# Create a list item with a text label and a thumbnail image.
		list_item = xbmcgui.ListItem(label=genreName)
		list_item.setInfo('video', {'title': genreName,
									'genre': genreName,
									#'tagline': genre['data-tooltip'],
									'plot' : genre['data-tooltip'],
									'plotoutline' : genre['data-tooltip'],
									'mediatype': 'video'})
		# Create a URL for a plugin recursive call.
		# Example: plugin://plugin.video.example/?action=listing&category=Animals
		url = get_url(action='listing', category="Genre", genre=genreName, url=genre.a['href'])
		# is_folder = True means that this item opens a sub-list of lower level items.
		is_folder = True
		# Add our item to the Kodi virtual folder listing.
		xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
	# Add a sort method for the virtual folder items (alphabetically, ignore articles)
	#xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
	# Finish creating a virtual folder.
	xbmcplugin.endOfDirectory(_handle)
	
def list_mainmenu():
	"""
	Create the list of video categories in the Kodi interface.
	"""
	# Set plugin category. It is displayed in some skins as the name
	# of the current section.
	xbmcplugin.setPluginCategory(_handle, 'Main Page')
	# Set plugin content. It allows Kodi to select appropriate views
	# for this type of content.
	xbmcplugin.setContent(_handle, 'files')
	# Get video categories
	categories = VIDEOS.iterkeys()
	# Iterate through categories
	for category in categories:
		# Create a list item with a text label and a thumbnail image.
		list_item = xbmcgui.ListItem(label=category)
		# Set graphics (thumbnail, fanart, banner, poster, landscape etc.) for the list item.
		# Here we use the same image for all items for simplicity's sake.
		# In a real-life plugin you need to set each image accordingly.
		'''list_item.setArt({'thumb': VIDEOS[category][0]['thumb'],
						  'icon': VIDEOS[category][0]['thumb'],
						  'fanart': VIDEOS[category][0]['thumb']})'''
		# Set additional info for the list item.
		# Here we use a category name for both properties for for simplicity's sake.
		# setInfo allows to set various information for an item.
		# For available properties see the following link:
		# https://codedocs.xyz/xbmc/xbmc/group__python__xbmcgui__listitem.html#ga0b71166869bda87ad744942888fb5f14
		# 'mediatype' is needed for a skin to display info for this ListItem correctly.
		list_item.setInfo('video', {'title': category,
									'genre': category,
									'mediatype': 'video'})
		# Create a URL for a plugin recursive call.
		# Example: plugin://plugin.video.example/?action=listing&category=Animals
		url = get_url(action='listing', category=category)
		# is_folder = True means that this item opens a sub-list of lower level items.
		is_folder = True
		# Add our item to the Kodi virtual folder listing.
		xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
	# Add a sort method for the virtual folder items (alphabetically, ignore articles)
	#xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
	# Finish creating a virtual folder.
	xbmcplugin.endOfDirectory(_handle)

#Latest and Latest episodes has a minimal list on the site, because they link to episodes.
def list_anime_series_minimal(category):
	site = requests.get(VIDEOS[category])
	soup = BeautifulSoup(site.text, "html.parser")
	episodesList = soup.find(class_="pd20").find_all("a")
	#seriesList = [i.get_text() for i in ss]
	
	xbmcplugin.setPluginCategory(_handle, category)
	xbmcplugin.setContent(_handle, 'videos')
	for video in episodesList:
		list_item = xbmcgui.ListItem(label=video.get_text())
		'''list_item.setArt({'thumb': VIDEOS[category][0]['thumb'],
						  'icon': VIDEOS[category][0]['thumb'],
						  'fanart': VIDEOS[category][0]['thumb']})'''
		list_item.setInfo('video', {'title': video.get_text(),
									'genre': video.get_text(),
									'mediatype': 'video'})
		if category == "Latest Episodes":
			# Set 'IsPlayable' property to 'true'.
			# This is mandatory for playable items!
			list_item.setProperty('IsPlayable', 'true')
			url = get_url(action='play', video=video['href'])
			#if false, won't open a new page
			is_folder = False
		else:
			url = get_url(action='seriesListing', show=video['href'])
			is_folder = True
		xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
	#xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
	xbmcplugin.endOfDirectory(_handle)
	
#For top individual episodes (most fapped, genre results, etc)
def list_anime_series_full(category, site_response=None):
	if site_response != None:
		site = site_response
	else:
		site = requests.get(VIDEOS[category])
	soup = BeautifulSoup(site.text, "html.parser")
	videoList = soup.find(id="brick-wrap").find_all("div", recursive=False)
	xbmcplugin.setPluginCategory(_handle, "WHAT DOES THIS DO???")
	#Tells skins that this is a listing of videos and such
	#skins usually don't use year unless you tell them it's a movie
	xbmcplugin.setContent(_handle, 'movies')
	
	#Generate a Kodi list item for every video
	for video in videoList:
	
		videoURL = grab_first_source(video.find('a', attrs={'class':'thumbnail-image'})['href'])
		#Don't add if the link is dead.
		if videoURL == None:
			continue
		url = get_url(action='play', video=videoURL)
		
		title = video.find(class_="brick-content").h3.text.strip()
		thumb = video.div.span.find(class_="thumbnail-image").img.get('data-src')
		list_item = xbmcgui.ListItem(label=title)
		list_item.setArt({'thumb': thumb,
						  'icon': thumb,
						  'fanart': thumb})
						  
		flyoutContent = video.find(class_="flyoutContent")
		info = {'title': title,
				#due to low quality coding many skins don't support genres in lists, so convert to string
				'genre': ", ".join([i.get_text() for i in flyoutContent.span.find_all("a")]),
				'tvshowtitle' : flyoutContent.a.text,
				#'year' : int(flyoutContent.p.text),
				#'year' : 2018,
				#'date' : "01.01.2018",
				'plot' : flyoutContent.find(class_="description", recursive=False).text,
				#'playcount' : int(''.join(c for c in video.find(class_="social-info").span.text if c.isdigit())),
				'mediatype': 'episode'}
		#Because apparently HH isn't consistent and sometimes doesn't have the year it was produced.
		if flyoutContent.find(class_="r_year"):
			year = flyoutContent.find(class_="r_year").text
			info['year'] = int(year)
			
		list_item.setInfo('video', info)
		# action: What screen you want the item to go to when clicked on
		# url: The URL of the video, duh
		#If this is true, clicking on it will open a new directory screen.
		is_folder = False
		#If it's a playable video. THIS HAS TO BE TRUE IF IT'S A SOURCE PICKER THAT SETS THE PLAYING VIDEO.
		list_item.setProperty('IsPlayable', 'true')
		xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
		break
	#It shows extra pages for genre and search, so add a next page button if there is one.
	"""extraPages = soup.find(class_="pagination")
	if extraPages != None:
		curPage, pages = [int(i) for i in extraPages.span.get_text().split("/")]
		if curPage < pages:
			list_item = xbmcgui.ListItem(label="Next Page")
			#It's broken
			url = get_url(action='listing', category="Genre", genre=category + " Page " + str(curPage+1), url=site.url+"/"+str(curPage+1))
			is_folder = True
			#BROKEN
			#xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder) """
	#xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
	xbmcplugin.endOfDirectory(_handle)
	
def list_anime_episodes(url):
	"""
	Create the list of playable videos in the Kodi interface.

	:param category: Category name
	:type category: str
	"""
	
	site = requests.get(url)
	soup = BeautifulSoup(site.text, "html.parser")
	details = soup.find(class_="content-detail")
	#Genre will always be the same, so we only make the string once.
	genre = ', '.join([i.get_text() for i in details.find_all(class_="tag")])
	#Same for the thumbnail..
	img = details.div.img['src']
	#and the description... Why must this site do this to me
	desc = details.find_all('span')[-1].next_sibling.strip()
	#And the title, which we want to use to remove it from the episode listings.
	title = details.h1.get_text()
	titleLen = len(title)+1
	videos = soup.find(class_="pd20").find_all('a')
	
	# Set plugin category. It is displayed in some skins as the name
	# of the current section.
	xbmcplugin.setPluginCategory(_handle, title)
	# Set plugin content. It allows Kodi to select appropriate views
	# for this type of content.
	xbmcplugin.setContent(_handle, 'episodes')
	# Iterate through videos.
	for video in videos:
		# Create a list item with a text label and a thumbnail image.
		list_item = xbmcgui.ListItem(label=video.get_text())
		# Set additional info for the list item.
		# 'mediatype' is needed for skin to display info for this ListItem correctly.
		list_item.setInfo('video', {
									'title': video.get_text()[titleLen:],
									'genre': genre,
									'mediatype': 'video',
									'plot': desc
})
		# Set graphics (thumbnail, fanart, banner, poster, landscape etc.) for the list item.
		# Here we use the same image for all items for simplicity's sake.
		# In a real-life plugin you need to set each image accordingly.
		list_item.setArt({
			'thumb': img,
			'icon': img,
			'fanart': img}
		)
		# Set 'IsPlayable' property to 'true'.
		# This is mandatory for playable items!
		list_item.setProperty('IsPlayable', 'true')
		# Create a URL for a plugin recursive call.
		# Example: plugin://plugin.video.example/?action=play&video=http://www.vidsplay.com/wp-content/uploads/2017/04/crab.mp4
		url = get_url(action='play', video=video['href'])
		# Add the list item to a virtual Kodi folder.
		# is_folder = False means that this item won't open any sub-list.
		is_folder = False
		# Add our item to the Kodi virtual folder listing.
		xbmcplugin.addDirectoryItem(_handle, url, list_item, is_folder)
	# Add a sort method for the virtual folder items (alphabetically, ignore articles)
	xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL_IGNORE_THE)
	# Finish creating a virtual folder.
	xbmcplugin.endOfDirectory(_handle)


def play_video(path):
	"""
	Play a video by the provided path.

	:param path: Fully-qualified video URL
	:type path: str
	"""
	print("Playing video "+path)
	# Create a playable item with a path to play.
	play_item = xbmcgui.ListItem(path=path)
	# Pass the item to the Kodi player.
	xbmcplugin.setResolvedUrl(_handle, True, listitem=play_item)

'''
def decrypt_stream_moe(url):
	#Get HTML of the embedded video player
	site = requests.get(url).text
	#Search for the base64 encoded HTML inside the embedded player
	b64 = site[site.find("atob("):].split("\n")[0][:-3]
	#decode it
	realSite = base64.b64decode(b64)
	soup = BeautifulSoup(realSite, "html.parser")
	#Finally, we have the actual video URL.
	return soup.find("video").source['src']
'''

def grab_first_source(url):
	print("Searching "+url)
	soup = BeautifulSoup(requests.get(url).text, "html.parser")
	#HentaiHaven randomizes the tab names because fuck me, but using class names is one way to get around it
	sources = soup.find("div", {"class":"ui-tabs-panel ui-widget-content ui-corner-bottom"})
	video = sources.find("video")
	if video != None:
		print("Found video: ("+video.source['data-res']+"p) "+video.source['src'])
		return video.source['src']
	else:
		print("No videos found...")
		return None

#HH doesn't have mirrors anymore, don't bother with this.
def list_available_sources(url):
	busydialog = xbmcgui.DialogBusy()
	busydialog.create()
	#entries = ["test", "test2", "test3"]
	entries = []
	soup = BeautifulSoup(requests.get(url).text, "html.parser")
	hhSources = soup.find(class_="download-panel").find_all('a')
	for source in hhSources:
		#list_item = xbmcgui.ListItem(label="HentaiHaven ("+source.span.text+")")
		#list_item.setInfo(
		entries.append({'url':source['href'], 'name':"HentaiHaven ("+source.span.text+")"})
	hhMirrors = [i['src'] for i in soup.find(class_="cube-loader-wrapper").next_sibling.find_all("iframe")]
	mirrorQualities = [i.a.text.split(" ")[-1] for i in soup.find(class_="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").find_all("li")[1:-1]] #Skip the first since it's the default, skip the last since it's the image preview
	for i in range(len(hhMirrors)):
		"""if mirror.startswith("https://stream.moe"):
			try:
				url = decrypt_stream_moe(mirror)
				entries.append({'url':url, 'name':"Stream.moe (???)"})
			except:
				xbmcgui.Dialog().notification("Stream.moe decryptor","Decryption of source failed.", xbmcgui.NOTIFICATION_INFO, 5000)
				print(mirror)"""
		entries.append({'url':urlresolver.resolve(hhMirrors[i]), 'name': urlparse(hhMirrors[i]).netloc + " " + mirrorQualities[i]})
		#entries.append({'url':urlresolver.resolve(hhMirrors[i]), 'name': "Mirror"})
		#except:
		#	xbmcgui.Dialog().notification("URLResolver","Decryption of mirror failed.", xbmcgui.NOTIFICATION_INFO, 5000)
		#	print("URLResolver failed to resolve " + hhMirrors[i])
	busydialog.close()
	sel = xbmcgui.Dialog().select("Choose a source", [e['name'] for e in entries])
	if sel == -1:
		return None
	else:
		print("User selected "+str(sel))
		#play_video(entries[sel]['url'])
		path = entries[sel]['url']
		#url = get_url(action='videoPlayer', url=path)
		print("INFO: Playing " + path)
		play_video(path)
		# Create a playable item with a path to play.
		#play_item = xbmcgui.ListItem(path=path)
		#play_item.setProperty('IsPlayable', 'true') #has no effect
		# Pass the item to the Kodi player.
		#xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem=play_item)


	
def router(paramstring):
	"""
	Router function that calls other functions
	depending on the provided paramstring

	:param paramstring: URL encoded plugin paramstring
	:type paramstring: str
	"""
	# Parse a URL-encoded paramstring to the dictionary of
	# {<parameter>: <value>} elements
	params = dict(parse_qsl(paramstring))
	# Check the parameters passed to the plugin
	if params:
		if params['action'] == 'listing':
			# Display the list of videos in a provided category.
			#list_videos(params['category'])
			#xbmcgui.Dialog().notification("Test", VIDEOS[params['category']])
			#NOT THE SAME AS GENRES! This is a specific genre, not the genres listing!
			if params['category'] == "Genre":
				list_anime_series_full(params['genre'], requests.get(params['url']))
			elif params['category'] == "Search":
				search()
			elif params['category'] == "Genres":
				list_genres()
			else:
				list_anime_series_full(params['category'])
		elif params['action'] == 'seriesListing':
			list_anime_episodes(params['show'])
		elif params['action'] == "sourcePicker":
			list_available_sources(params['url'])
		elif params['action'] == 'play':
			# Play a video from a provided URL.
			play_video(params['video'])
		else:
			# If the provided paramstring does not contain a supported action
			# we raise an exception. This helps to catch coding errors,
			# e.g. typos in action names.
			raise ValueError('Invalid paramstring: {0}!'.format(paramstring))
	else:
		# If the plugin is called from Kodi UI without any parameters,
		# display the list of video categories
		list_mainmenu()


if __name__ == '__main__':
	# Call the router function and pass the plugin call parameters to it.
	# We use string slicing to trim the leading '?' from the plugin call paramstring
	router(sys.argv[2][1:])
